package cn.com.oyat.idea.service;

import cn.com.oyat.idea.model.DlnaDevice;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.springframework.stereotype.Service;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.net.URL;

@Service
public class VideoPushService {

    /**
     * 向指定设备推送视频URL
     *
     * @param device   目标DLNA设备
     * @param videoUrl 要推送的视频URL（必须是设备能访问的地址，如公网URL或局域网内共享）
     */
    public boolean pushVideoToDevice(DlnaDevice device, String videoUrl) {
        try {
            // 1. 从设备描述文档中获取AVTransport服务的控制URL
            String controlURL = getAvTransportControlUrl(device.getLocation());
            if (controlURL == null) {
                System.err.println("Could not find AVTransport service for device: " + device.getFriendlyName());
                return false;
            }

            // 2. 构建完整的控制URL（可能是相对路径）
            URL baseUrl = new URL(device.getLocation());
            URL fullControlUrl = new URL(baseUrl, controlURL);

            // 3. 发送SetAVTransportURI命令
            boolean setUriSuccess = sendSetAvTransportUri(fullControlUrl.toString(), videoUrl);
            if (!setUriSuccess) {
                return false;
            }

            // 4. 发送Play命令
            return sendPlayCommand(fullControlUrl.toString());

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 从设备描述XML中解析AVTransport服务的控制URL
     */
    private String getAvTransportControlUrl(String deviceDescriptionUrl) throws Exception {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet request = new HttpGet(deviceDescriptionUrl);
            try (CloseableHttpResponse response = httpClient.execute(request)) {
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    String xmlContent = EntityUtils.toString(entity);
                    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                    // 防止XXE攻击
                    factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
                    DocumentBuilder builder = factory.newDocumentBuilder();
                    Document doc = builder.parse(new ByteArrayInputStream(xmlContent.getBytes()));

                    // 查找serviceType为"AVTransport"的服务
                    NodeList serviceList = doc.getElementsByTagName("service");
                    for (int i = 0; i < serviceList.getLength(); i++) {
                        org.w3c.dom.Node serviceNode = serviceList.item(i);
                        NodeList serviceChildren = serviceNode.getChildNodes();
                        String serviceType = "";
                        String controlUrl = "";

                        for (int j = 0; j < serviceChildren.getLength(); j++) {
                            org.w3c.dom.Node child = serviceChildren.item(j);
                            if ("serviceType".equals(child.getNodeName())) {
                                serviceType = child.getTextContent();
                            } else if ("controlURL".equals(child.getNodeName())) {
                                controlUrl = child.getTextContent();
                            }
                        }

                        if ("urn:schemas-upnp-org:service:AVTransport:1".equals(serviceType)) {
                            return controlUrl;
                        }
                    }
                    EntityUtils.consume(entity);
                }
            }
        }
        return null;
    }

    /**
     * 发送SetAVTransportURI SOAP请求
     */
    private boolean sendSetAvTransportUri(String controlUrl, String videoUrl) throws Exception {
        String soapBody = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                "<s:Envelope s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" " +
                "xmlns:s=\"http://schemas.xmlsoap.org/soap/\">" +
                "<s:Body>" +
                "<u:SetAVTransportURI xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\">" +
                "<InstanceID>0</InstanceID>" +
                "<CurrentURI>" + escapeXml(videoUrl) + "</CurrentURI>" +
                "<CurrentURIMetaData></CurrentURIMetaData>" +
                "</u:SetAVTransportURI>" +
                "</s:Body>" +
                "</s:Envelope>";

        return sendSoapRequest(controlUrl, soapBody, "SetAVTransportURI");
    }

    /**
     * 发送Play SOAP请求
     */
    private boolean sendPlayCommand(String controlUrl) throws Exception {
        String soapBody = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                "<s:Envelope s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" " +
                "xmlns:s=\"http://schemas.xmlsoap.org/soap/\">" +
                "<s:Body>" +
                "<u:Play xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\">" +
                "<InstanceID>0</InstanceID>" +
                "<Speed>1</Speed>" +
                "</u:Play>" +
                "</s:Body>" +
                "</s:Envelope>";

        return sendSoapRequest(controlUrl, soapBody, "Play");
    }

    /**
     * 发送SOAP请求的通用方法
     */
    private boolean sendSoapRequest(String controlUrl, String soapBody, String action) throws Exception {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost request = new HttpPost(controlUrl);

            // 设置SOAPAction Header
            request.setHeader("SOAPAction", "\"urn:schemas-upnp-org:service:AVTransport:1#" + action + "\"");
            request.setHeader("Content-Type", "text/xml; charset=\"utf-8\"");

            StringEntity stringEntity = new StringEntity(soapBody);
            request.setEntity(stringEntity);

            try (CloseableHttpResponse response = httpClient.execute(request)) {
                int statusCode = response.getCode();
                // UPnP操作成功通常返回200
                return statusCode == 200;
            }
        }
    }

    private String escapeXml(String text) {
        return text.replace("&", "&amp;")
                .replace("<", "&lt;")
                .replace(">", "&gt;")
                .replace("\"", "&quot;")
                .replace("'", "&apos;");
    }
}